package com.example.controller;

import com.example.domain.Lecture;
import com.example.domain.User;
import com.example.dto.*;
import com.example.service.LectureService;
import com.example.service.UserService;
import com.example.util.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;

import java.util.List;
import java.util.Map;

/**
 * 讲座管理控制器
 * 
 * @author HP
 * @description 讲座管理相关接口
 * @createDate 2025-08-26 22:00:00
 */
@Tag(name = "讲座管理", description = "讲座相关接口")
@RestController
@RequestMapping("/api")
public class LectureController {

    @Resource
    private UserService userService;

    @Resource
    private LectureService lectureService;

    // ==================== 公开查询接口 ====================

    /**
     * 查询所有讲座
     */
    @Operation(summary = "查询讲座列表", description = "查询所有讲座信息")
    @GetMapping("/lectures")
    public Result getAllLectures() {
        try {
            Long userId = getCurrentUserId(); // 获取当前用户ID，可能为null
            List<com.example.vo.LectureVO> lectures = lectureService.listAllLecturesWithDetails(userId);
            return Result.success(lectures);
        } catch (Exception e) {
            return Result.error("查询讲座列表失败：" + e.getMessage());
        }
    }

    /**
     * 查询讲座详情
     */
    @Operation(summary = "查询讲座详情", description = "根据ID查询讲座详细信息")
    @GetMapping("/lectures/{id}")
    public Result getLectureById(@Parameter(description = "讲座ID") @PathVariable Long id) {
        try {
            Long userId = getCurrentUserId(); // 获取当前用户ID，可能为null
            com.example.vo.LectureVO lecture = lectureService.getLectureWithDetails(id, userId);
            return Result.success(lecture);
        } catch (Exception e) {
            return Result.error("查询讲座详情失败：" + e.getMessage());
        }
    }

    /**
     * 查询讲座统计信息
     */
    @Operation(summary = "查询讲座统计", description = "查询讲座的报名和签到统计信息")
    @GetMapping("/lectures/{id}/statistics")
    public Result getLectureStatistics(@Parameter(description = "讲座ID") @PathVariable Long id) {
        try {
            Map<String, Object> statistics = lectureService.getRegistrationStatistics(id);
            return Result.success(statistics);
        } catch (Exception e) {
            return Result.error("查询讲座统计失败：" + e.getMessage());
        }
    }

    /**
     * 查询讲座剩余名额
     */
    @Operation(summary = "查询剩余名额", description = "查询讲座剩余名额数量")
    @GetMapping("/lectures/{id}/remaining-slots")
    public Result getRemainingSlots(@Parameter(description = "讲座ID") @PathVariable Long id) {
        try {
            int remainingSlots = lectureService.getRemainingSlots(id);
            return Result.success(Map.of("remainingSlots", remainingSlots));
        } catch (Exception e) {
            return Result.error("查询剩余名额失败：" + e.getMessage());
        }
    }

    // ==================== 用户功能接口 ====================

    /**
     * 用户报名讲座
     */
    @Operation(summary = "报名讲座", description = "用户报名参加讲座")
    @PostMapping("/lectures/{lectureId}/register")
    @PreAuthorize("hasAnyRole('USER', 'ADMIN')")
    public Result registerLecture(
            @Parameter(description = "讲座ID") @PathVariable Long lectureId) {
        
        try {
            Long userId = getCurrentUserId();
            if (userId == null) {
                return Result.error("用户未登录");
            }
            
            // 检查用户是否已经报名
            if (lectureService.hasUserRegistered(userId, lectureId)) {
                return Result.error("您已经报名该讲座，请勿重复报名");
            }
            
            boolean success = lectureService.reserveLecture(userId, lectureId);

            if (success) {
                return Result.success("报名成功");
            } else {
                return Result.error("报名失败");
            }
        } catch (Exception e) {
            return Result.error("报名失败：" + e.getMessage());
        }
    }

    /**
     * 用户取消报名
     */
    @Operation(summary = "取消报名", description = "用户取消讲座报名")
    @DeleteMapping("/lectures/{lectureId}/register")
    @PreAuthorize("hasAnyRole('USER', 'ADMIN')")
    public Result cancelRegistration(
            @Parameter(description = "讲座ID") @PathVariable Long lectureId) {
        
        try {
            Long userId = getCurrentUserId();
            boolean success = lectureService.cancelRegistration(userId, lectureId);

            if (success) {
                return Result.success("取消报名成功");
            } else {
                return Result.error("取消报名失败");
            }
        } catch (Exception e) {
            return Result.error("取消报名失败：" + e.getMessage());
        }
    }

    /**
     * 用户签到
     */
    @Operation(summary = "讲座签到", description = "用户通过报名记录ID签到参加讲座")
    @PostMapping("/lectures/checkin/{registrationId}")
    @PreAuthorize("hasAnyRole('USER', 'ADMIN')")
    public Result checkInLecture(
            @Parameter(description = "报名记录ID") @PathVariable Long registrationId) {
        
        try {
            Long userId = getCurrentUserId();
            boolean success = lectureService.checkInLectureByRegistrationId(userId, registrationId);

            if (success) {
                return Result.success("签到成功");
            } else {
                return Result.error("签到失败");
            }
        } catch (Exception e) {
            return Result.error("签到失败：" + e.getMessage());
        }
    }

    /**
     * 查询我的报名记录
     */
    @Operation(summary = "我的报名记录", description = "查询当前用户的讲座报名记录")
    @GetMapping("/lectures/my-registrations")
    @PreAuthorize("hasAnyRole('USER', 'ADMIN')")
    public Result getMyRegistrations() {
        try {
            Long userId = getCurrentUserId();
            List<Map<String, Object>> registrations = lectureService.getUserRegistrations(userId);
            return Result.success(registrations);
        } catch (Exception e) {
            return Result.error("查询报名记录失败：" + e.getMessage());
        }
    }

    /**
     * 查询报名状态
     */
    @Operation(summary = "查询报名状态", description = "查询用户在指定讲座的报名状态")
    @GetMapping("/lectures/{lectureId}/registration-status")
    @PreAuthorize("hasAnyRole('USER', 'ADMIN')")
    public Result getRegistrationStatus(@Parameter(description = "讲座ID") @PathVariable Long lectureId) {
        try {
            Long userId = getCurrentUserId();
            Map<String, Object> status = lectureService.getUserRegistrationStatus(userId, lectureId);
            return Result.success(status);
        } catch (Exception e) {
            return Result.error("查询报名状态失败：" + e.getMessage());
        }
    }

    // ==================== 管理员功能接口 ====================

    /**
     * 创建讲座
     */
    @Operation(summary = "创建讲座", description = "管理员创建新讲座")
    @PostMapping("/admin/lectures")
    @PreAuthorize("hasRole('ADMIN')")
    public Result createLecture(@Valid @RequestBody LectureRequestDTO requestDTO) {
        try {
            Lecture lecture = new Lecture();
            lecture.setTitle(requestDTO.getTitle());
            lecture.setLecturer(requestDTO.getLecturer());
//            lecture.setStartTime(requestDTO.getStartTime());
//            lecture.setEndTime(requestDTO.getEndTime());
            lecture.setContent(requestDTO.getDescription());
            lecture.setParticipantLimit(requestDTO.getParticipantLimit());
            lecture.setClassroomId(1L); // 暂时设置为固定值，实际应根据location查询
            lecture.setLectureStatus(0); // 未开始

            LectureAddDTO addDTO = new LectureAddDTO();
            BeanUtils.copyProperties(requestDTO, addDTO);

            boolean success = lectureService.addLecture(addDTO).getCode() == 200;
            if (success) {
                return Result.success("创建讲座成功");
            } else {
                return Result.error("创建讲座失败");
            }
        } catch (Exception e) {
            return Result.error("创建讲座失败：" + e.getMessage());
        }
    }

    /**
     * 更新讲座
     */
    @Operation(summary = "更新讲座", description = "管理员更新讲座信息")
    @PutMapping("/admin/lectures/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    public Result updateLecture(
            @Parameter(description = "讲座ID") @PathVariable Long id,
            @Valid @RequestBody LectureRequestDTO requestDTO) {
        
        try {
            Lecture lecture = lectureService.getLectureById(id);
            if (lecture == null) {
                return Result.error("讲座不存在");
            }

            lecture.setTitle(requestDTO.getTitle());
            lecture.setLecturer(requestDTO.getLecturer());
//            lecture.setStartTime(requestDTO.getStartTime());
//            lecture.setEndTime(requestDTO.getEndTime());
            lecture.setContent(requestDTO.getDescription());
            lecture.setParticipantLimit(requestDTO.getParticipantLimit());
            lecture.setClassroomId(1L); // 暂时设置为固定值，实际应根据location查询

            LectureUpdateDTO addDTO = new LectureUpdateDTO();
            BeanUtils.copyProperties(requestDTO, addDTO);

            boolean success = lectureService.updateLecture(addDTO).getCode() == 200;
            if (success) {
                return Result.success("更新讲座成功");
            } else {
                return Result.error("更新讲座失败");
            }
        } catch (Exception e) {
            return Result.error("更新讲座失败：" + e.getMessage());
        }
    }

    /**
     * 删除讲座
     */
    @Operation(summary = "删除讲座", description = "管理员删除讲座")
    @DeleteMapping("/admin/lectures/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    public Result deleteLecture(@Parameter(description = "讲座ID") @PathVariable Long id) {
        try {
            boolean success = lectureService.deleteLecture(id).getCode() == 200;
            if (success) {
                return Result.success("删除讲座成功");
            } else {
                return Result.error("删除讲座失败");
            }
        } catch (Exception e) {
            return Result.error("删除讲座失败：" + e.getMessage());
        }
    }

    /**
     * 管理员强制取消用户报名
     */
    @Operation(summary = "管理员取消报名", description = "管理员强制取消用户报名")
    @DeleteMapping("/admin/lectures/{lectureId}/registrations/{userId}")
    @PreAuthorize("hasRole('ADMIN')")
    public Result adminCancelRegistration(
            @Parameter(description = "讲座ID") @PathVariable Long lectureId,
            @Parameter(description = "用户ID") @PathVariable Long userId,
            @Valid @RequestBody RegistrationCancelRequestDTO requestDTO) {
        
        try {
            Long operatorId = getCurrentUserId();
            boolean success = lectureService.adminCancelRegistration(
                    userId, lectureId, operatorId, requestDTO.getReason());

            if (success) {
                return Result.success("管理员取消报名成功");
            } else {
                return Result.error("管理员取消报名失败");
            }
        } catch (Exception e) {
            return Result.error("管理员取消报名失败：" + e.getMessage());
        }
    }

    /**
     * 管理员代替用户签到
     */
    @Operation(summary = "管理员代替签到", description = "管理员代替用户签到")
    @PostMapping("/admin/lectures/{lectureId}/checkin/{userId}")
    @PreAuthorize("hasRole('ADMIN')")
    public Result adminCheckIn(
            @Parameter(description = "讲座ID") @PathVariable Long lectureId,
            @Parameter(description = "用户ID") @PathVariable Long userId) {
        
        try {
            Long operatorId = getCurrentUserId();
            boolean success = lectureService.adminCheckInLecture(userId, lectureId, operatorId);

            if (success) {
                return Result.success("管理员代替签到成功");
            } else {
                return Result.error("管理员代替签到失败");
            }
        } catch (Exception e) {
            return Result.error("管理员代替签到失败：" + e.getMessage());
        }
    }

    /**
     * 批量签到
     */
    @Operation(summary = "批量签到", description = "管理员批量签到操作")
    @PostMapping("/admin/lectures/{lectureId}/batch-checkin")
    @PreAuthorize("hasRole('ADMIN')")
    public Result batchCheckIn(
            @Parameter(description = "讲座ID") @PathVariable Long lectureId,
            @Valid @RequestBody AdminCheckInRequestDTO requestDTO) {
        
        try {
            Long operatorId = getCurrentUserId();
            Map<String, Object> result = lectureService.batchCheckIn(
                    lectureId, requestDTO.getUserIds(), operatorId);

            return Result.success(result);
        } catch (Exception e) {
            return Result.error("批量签到失败：" + e.getMessage());
        }
    }

    /**
     * 查询讲座报名列表
     */
    @Operation(summary = "查询报名列表", description = "管理员查询讲座的所有报名用户")
    @GetMapping("/admin/lectures/{lectureId}/registrations")
    @PreAuthorize("hasRole('ADMIN')")
    public Result getLectureRegistrations(@Parameter(description = "讲座ID") @PathVariable Long lectureId) {
        try {
            List<com.example.domain.User> users = lectureService.getLectureReservations(lectureId);
            return Result.success(users);
        } catch (Exception e) {
            return Result.error("查询报名列表失败：" + e.getMessage());
        }
    }

    /**
     * 查询签到列表
     */
    @Operation(summary = "查询签到列表", description = "管理员查询讲座的签到用户列表")
    @GetMapping("/admin/lectures/{lectureId}/checkin-list")
    @PreAuthorize("hasRole('ADMIN')")
    public Result getCheckInList(@Parameter(description = "讲座ID") @PathVariable Long lectureId) {
        try {
            List<Map<String, Object>> checkInList = lectureService.getLectureCheckInList(lectureId);
            return Result.success(checkInList);
        } catch (Exception e) {
            return Result.error("查询签到列表失败：" + e.getMessage());
        }
    }

    /**
     * 查询未签到列表
     */
    @Operation(summary = "查询未签到列表", description = "管理员查询讲座的未签到用户列表")
    @GetMapping("/admin/lectures/{lectureId}/not-checkin-list")
    @PreAuthorize("hasRole('ADMIN')")
    public Result getNotCheckInList(@Parameter(description = "讲座ID") @PathVariable Long lectureId) {
        try {
            List<Map<String, Object>> notCheckInList = lectureService.getLectureNotCheckInList(lectureId);
            return Result.success(notCheckInList);
        } catch (Exception e) {
            return Result.error("查询未签到列表失败：" + e.getMessage());
        }
    }

    /**
     * 取消签到
     */
    @Operation(summary = "取消签到", description = "管理员取消用户签到")
    @DeleteMapping("/admin/lectures/{lectureId}/checkin/{userId}")
    @PreAuthorize("hasRole('ADMIN')")
    public Result cancelCheckIn(
            @Parameter(description = "讲座ID") @PathVariable Long lectureId,
            @Parameter(description = "用户ID") @PathVariable Long userId,
            @Parameter(description = "取消原因") @RequestParam(required = false) String reason) {
        
        try {
            Long operatorId = getCurrentUserId();
            boolean success = lectureService.cancelCheckIn(userId, lectureId, operatorId, reason);

            if (success) {
                return Result.success("取消签到成功");
            } else {
                return Result.error("取消签到失败");
            }
        } catch (Exception e) {
            return Result.error("取消签到失败：" + e.getMessage());
        }
    }

    /**
     * 获取当前用户ID
     */
    /**
     * 获取当前登录用户ID
     * 从Security上下文中获取用户名，再查询用户ID
     */
    private Long getCurrentUserId() {
        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null && authentication.isAuthenticated() 
                && !"anonymousUser".equals(authentication.getPrincipal())) {
                
                String username = authentication.getName();
                if (username != null && !"anonymousUser".equals(username)) {
                    // 通过用户名查询用户ID
                    User user = userService.getUserByUsername(username);
                    return user != null ? user.getId() : null;
                }
            }
            return null; // 未登录用户返回null
        } catch (Exception e) {
            return null; // 异常情况返回null
        }
    }
}